/* Peter Banda, Daniel Cristofani, Dominic Tippabattuni                     */
/* 975530978    971012079          958842138                                */
/* VMM_Sim Implementation (assignment 5)                                    */
/* CS 538, Portland State University, Fall 2010                             */
/* Turned in November 18, 2010                                              */

/* historycollector.c contains functions that are called mostly by vmm.c    */
/* and inputhandler.c, to record data (some statically, some dynamically).  */

#include "vmm.h"

struct Stats stats;
struct CommandLogEntry *commandLog;	//All commands so far
struct CommandLogEntry *commandLogTailPtr;	//Saves time, enqueue at tail

//function to allocate a new node for global linked list.
struct CommandLogEntry *newCommandLogEntry(void)
{
    struct CommandLogEntry *newnode;
    newnode = malloc(sizeof(struct CommandLogEntry));
    if (!newnode)
	error("The simulator has run out of memory. Please increase its memory allocation or run it without -t.");
    return newnode;
}

// increments the reads counter.
void recordRead()
{
	stats.reads++;
}

// increments the writes counter.
void recordWrite()
{
	stats.writes++;
}

// increments swaps in counter.
void recordSwapIn()
{
	stats.swapIns++;
}

// records swap in.
void recordSwapOut()
{
	stats.swapOuts++;
}

// records replacement.
void recordReplacement()
{
	stats.replacements++;
}

//  increments existingPageTableCount counter.
void recordPTExists()
{
	stats.existingPageTableCount++;
}

//  increments existingUserPageCount counter.
void recordUPExists()
{
	stats.existingUserPageCount++;
}

// increments residentPageTableCount counter. Set residentPageTableMax if actual value exceeds it.
void recordPTResident()
{
	if (++stats.residentPageTableCount>stats.residentPageTableMax){
		stats.residentPageTableMax=stats.residentPageTableCount;
	}
}

// increments residentUserPageCount counter. Set  residentUserPageMax if actual value exceeds it.
void recordUPResident()
{
	if (++stats.residentUserPageCount>stats.residentUserPageMax){
		stats.residentUserPageMax=stats.residentUserPageCount;
	}
}

//  decrements residentPageTableCount counter.
void recordPTNonResident()
{
	stats.residentPageTableCount--;
}

//  decrements residentUserPageCount counter.
void recordUPNonResident()
{
	stats.residentUserPageCount--;
}

// returns Stats containing all global access statistics to be used by StatsPrinter.
struct Stats getStats()
{
	return stats;
}

// returns a pointer to CommandLog to be used by StatsPrinter.
struct CommandLogEntry *getCommandLog()
{
    return commandLog;
}

// adds an item to the tail of the CommandLog, recording a command that was executed.
void addToCommandLog(enum TypeOfAccess accessType, unsigned long address)
{
    struct CommandLogEntry *temp;
    temp = newCommandLogEntry();
    temp->access = accessType;
    temp->address = address;
    temp->next = 0;
    if (commandLogTailPtr) {
	commandLogTailPtr->next = temp;
	commandLogTailPtr = temp;
    } else {
	commandLog = commandLogTailPtr = temp;
    }
}

unsigned long getTotalAccesses(void)
{
    return (stats.reads + stats.writes);
}

